package org.dftproject.genesis.ui.presentation.tabcontrol;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Iterator;

import org.dftproject.genesis.ui.SharedImages;
import org.dftproject.genesis.ui.figures.CloseButtonFigure;
import org.dftproject.genesis.ui.figures.ColumnData;
import org.dftproject.genesis.ui.figures.ColumnLayout;
import org.dftproject.genesis.ui.figures.ISelectionListener;
import org.dftproject.genesis.ui.figures.TooltipLabel;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.MouseMotionListener;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;

public class TabFigure extends Figure {
	
	protected final Font boldFont = JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT);

	protected final TabControlFigure parent;
	protected TabItem item;

	protected final Label label;
	protected final CloseButtonFigure closeBtn;

	protected boolean selected;
	protected boolean hover;
	protected boolean closable = true;

	public TabFigure(TabControlFigure parent) {
		this.parent = parent;
		
		ColumnLayout layout = new ColumnLayout();
		layout.setSpacing(5);
		setLayoutManager(layout);
		
		setBorder(new MarginBorder(5, 7, 5, 7));
		
		label = new Label();
		label.setLabelAlignment(PositionConstants.LEFT);
		label.setIcon(SharedImages.getDefault().getImage(SharedImages.IMG_NULL));
		label.setIconTextGap(5);
		add(label, new ColumnData(1));
		
		closeBtn = new CloseButtonFigure();
		closeBtn.addMouseMotionListener(new MouseMotionListener.Stub() {

			@Override
			public void mouseEntered(MouseEvent me) {
				repaint();
			}
			
			@Override
			public void mouseExited(MouseEvent me) {
				repaint();
			}
			
		});
		closeBtn.addSelectionListener(new ISelectionListener() {

			public void selected() {
				if (item != null)
					item.getTabControl().closeTabItem(item);
			}
			
		});
		closeBtn.addPropertyChangeListener(CloseButtonFigure.HOVER_STATE, new PropertyChangeListener() {

			public void propertyChange(PropertyChangeEvent event) {
				repaint();
			}
			
		});
		closeBtn.setToolTip(new TooltipLabel("Close Tab"));
		add(closeBtn, new ColumnData());

		setRequestFocusEnabled(true);
		addListeners();
	}
	
	public TabFigure(TabControlFigure parent, final TabItem item) {
		this(parent);
		this.item = item;		
	}

	protected void addListeners() {
		MouseTracker tracker = new MouseTracker();
		addMouseMotionListener(tracker);
		addMouseListener(tracker);
	}

	public boolean isSelected() {
		return selected;
	}

	public void setSelected(boolean selected) {
		if (this.selected == selected)
			return;
		this.selected = selected;
		closeBtn.setSelected(selected);
		label.setFont(selected ? boldFont : getFont());
		repaint();
	}

	@Override
	public Dimension getPreferredSize(int wHint, int hHint) {
		return new Dimension(200, super.getPreferredSize(wHint, hHint).height);
	}

	@Override
	public void paintFigure(Graphics graphics) {
		drawButton(graphics);
		super.paintFigure(graphics);
	}

	private final Color hoverTopTop = new Color(null, 255, 255, 255);
	private final Color hoverTopBottom = new Color(null, 255, 231, 144);
	private final Color hoverBottomTop = new Color(null, 255, 215, 76);
	private final Color hoverBottomBottom = new Color(null, 255, 231, 144);

	private final Color selectedTopTop = new Color(null, 255, 255, 255);
	private final Color selectedTopBottom = new Color(null, 234, 244, 255);
	private final Color selectedBottomTop = new Color(null, 196, 225, 255);
	private final Color selectedBottomBottom = new Color(null, 234, 244, 255);
	
	private final Color normalTopTop = new Color(null, 244, 244, 244);
	private final Color normalTopBottom = new Color(null, 225, 225, 225);
	private final Color normalBottomTop = new Color(null, 206, 206, 206);
	private final Color normalBottomBottom = new Color(null, 244, 244, 244);

	public void drawButton(Graphics graphics) {
		graphics.pushState();
		Rectangle bounds = getBounds();
		Rectangle innerBounds = bounds.getCropped(new Insets(0, 1, 0, 1));
		if (hover || closeBtn.isHover()) {
			graphics.setForegroundColor(hoverTopTop);
			graphics.setBackgroundColor(hoverTopBottom);
			graphics.fillGradient(innerBounds.getResized(0, -innerBounds.height / 2), true);

			graphics.setForegroundColor(hoverBottomTop);
			graphics.setBackgroundColor(hoverBottomBottom);
			graphics.fillGradient(innerBounds.getResized(0, -innerBounds.height / 2).getTranslated(0, innerBounds.height / 2), true);
		} else if (selected) {
			graphics.setForegroundColor(selectedTopTop);
			graphics.setBackgroundColor(selectedTopBottom);
			graphics.fillGradient(innerBounds.getResized(0, -innerBounds.height / 2), true);

			graphics.setForegroundColor(selectedBottomTop);
			graphics.setBackgroundColor(selectedBottomBottom);
			graphics.fillGradient(innerBounds.getResized(0, -innerBounds.height / 2).getTranslated(0, innerBounds.height / 2), true);
		} else {			
			graphics.setForegroundColor(normalTopTop);
			graphics.setBackgroundColor(normalTopBottom);
			graphics.fillGradient(innerBounds.getResized(0, -innerBounds.height / 2), true);

			graphics.setForegroundColor(normalBottomTop);
			graphics.setBackgroundColor(normalBottomBottom);
			graphics.fillGradient(innerBounds.getResized(0, -innerBounds.height / 2).getTranslated(0, innerBounds.height / 2), true);
		}
		
		graphics.setAntialias(SWT.ON);
		graphics.setForegroundColor(ColorConstants.white);
		graphics.setLineWidth(2);
		graphics.drawRoundRectangle(bounds.getCropped(new Insets(1)).resize(0, 3), 6, 6);
		graphics.setForegroundColor(parent.getBorderColor());
		graphics.setLineWidth(1);
		graphics.drawRoundRectangle(bounds.getResized(-1, -1).resize(0, 3), 6, 6);
		graphics.setAntialias(SWT.OFF);
		
		if (!selected)
			graphics.drawLine(bounds.x + 1, bounds.bottom() - 1, bounds.right() - 2, bounds.bottom() - 1);

		graphics.popState();
	}

	public void setText(String text) {
		label.setText(text);
		setToolTip(new TooltipLabel(text));
	}

	public void setIcon(Image icon) {
		label.setIcon(icon);
	}

	protected class MouseTracker extends MouseMotionListener.Stub implements MouseListener {

		public void mousePressed(MouseEvent me) {
			if (me.button == 1) {
				requestFocus();
				me.consume();
	
				if (getBounds().contains(me.getLocation()))
					handleSelected();
			}
		}

		public void mouseReleased(MouseEvent me) {
		}

		public void mouseDoubleClicked(MouseEvent me) {
		}

		@Override
		public void mouseEntered(MouseEvent me) {
			hover = true;
			repaint();
		}

		@Override
		public void mouseExited(MouseEvent me) {
			hover = false;
			repaint();
		}

		@Override
		public void mouseDragged(MouseEvent me) {
			hover = getBounds().contains(me.getLocation());
			repaint();
		}

	}

	public boolean isClosable() {
		return closable;
	}

	public void setClosable(boolean closable) {
		this.closable = closable;
		closeBtn.setVisible(closable);
	}
	
	public void addSelectionListener(ISelectionListener listener) {
		addListener(ISelectionListener.class, listener);
	}
	
	public void removeSelectionListener(ISelectionListener listener) {
		removeListener(ISelectionListener.class, listener);
	}

	protected void handleSelected() {
		Iterator<?> iter = getListeners(ISelectionListener.class);
		while (iter.hasNext())
			((ISelectionListener) iter.next()).selected();
	}

}
